<!DOCTYPE html>
<html class="no-js" lang="zh">
  <head>
<meta charset="utf-8">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="alternate" href="https://www.desgard.com" hreflang="pt-BR">
<link href="http://gmpg.org/xfn/11" rel="profile">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="theme-color" content="#005344">
<title>Guardia · 瓜地</title>
<meta name="google-site-verification" content="zS1dSn20XtA4FJYEOQLXqI0boxZdMnJ2g3beje-cl20">
<meta name="description" content="I write many code to write less code.💻">
<meta name="keywords" content="">
<!-- Social: Facebook / Open Graph -->
<meta property="og:url" content="https://www.desgard.com/Running-Or-Safe/">
<meta property="og:title" content="       玩转运动世界校园 | Gua  ">
<meta property="og:description" content="I write many code to write less code.💻">
<meta property="og:site_name" content="Desgard_Duan">
<meta property="og:locale" content="pt_BR">
<meta property="og:type" content="website">
<meta property="og:author" content="https://www.facebook.com/desgard.duan">
<meta property="og:image" content="https://www.desgard.com">
<!-- Social: Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@nandomoreirame">
<meta name="twitter:domain" content="https://www.desgard.com">
<meta name="twitter:title" content="       玩转运动世界校园 | Gua  ">
<meta name="twitter:description" content="I write many code to write less code.💻">
<meta name="twitter:image:src" content="https://www.desgard.com">
<!-- Favicons -->
<link rel="apple-touch-icon" sizes="114x114" href="https://www.desgard.com/assets/ico/apple-touch-icon-114-516f4e19976b9e4dbb77ad9b576831fe.png">
<link rel="apple-touch-icon" sizes="72x72" href="https://www.desgard.com/assets/ico/apple-touch-icon-72-5409b2df229305703caf583d86c845ab.png">
<link rel="apple-touch-icon" href="https://www.desgard.com/assets/ico/apple-touch-icon-57-aa873e019cf659e0d4e6a0b5bb9f379d.png">
<link rel="shortcut icon" href="https://www.desgard.com/assets/ico/favicon-4298be3d3fbe23e18d65bded9d930899.png">
<!-- rel prev and next -->
<!-- Canonical link tag -->
<link rel="canonical" href="https://www.desgard.com/Running-Or-Safe/">
<link rel="alternate" type="application/rss+xml" title="Gua" href="https://www.desgard.com/feed.xml">
<link rel="stylesheet" href="/assets/main-0b7b828712f4c43b75bba4861c907bb1.css">
<script src="/assets/modernizr-custom-cb807611a3e262b2eac59444cbab74d6.js" data-cfasync="false"></script>
<script src="/assets/js/jquery-3.1.js"></script>
<script src="/assets/js/jquery.rotate.js"></script>
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "Website",
  "publisher": "www.desgard.com",
  "url": "http://www.desgard.com/",
  "description": "瓜地"
}
</script>
<script type="text/javascript">
  var disqus_shortname = 'desgard',
      baseurl          = '';
</script>
<!--
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-52446115-1']);
_gaq.push(['_trackPageview']);
(function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>-->
<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "//hm.baidu.com/hm.js?c5a8123bc51782a3083a631ed9ff50e4";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
      tex2jax: {
        inlineMath: [ ['$','$'] ],
        displayMath: [ ['$$','$$'] ],
        processEscapes: true
      }
    });
  </script>
  </head>
  <body class="post-template single">
    <header class="header">
  <div class="container">
    <h1><a href="/"><strong>desgard</strong>.com</a></h1>
    <nav class="navbar">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="#!" data-modal="modalSearch"><i class="fa fa-search"></i></a></li>
        <li><a href="/comment " target="_blank"><i class="fa fa-comments"></i></a></li>
        <li><a href="/feed.xml" target="_blank"><i class="fa fa-feed"></i></a></li>
      </ul>
    </nav>
  </div>
</header>
    <main class="wrapper container" itemprop="mainContentOfPage" itemscope="itemscope" itemtype="http://schema.org/Blog">
      <article class="post" itemscope="itemscope" itemtype="http://schema.org/BlogPosting" itemprop="blogPost">
  <header class="post-header">
    <h1>玩转运动世界校园</h1>
    <div class="post-meta">
      <time datetime="2015-10-13">
        <i class="fa fa-calendar-o"></i> <time datetime="2016-11-03"> 2016-11-03
      </time>
      <span>
        <i class="fa fa-comments"></i> <a href="#container">Comment me!</a>
      </span>
      <span>
<!--
        <i class="fa fa-folder-open-o"></i> 
-->
      </span>
    </div>
  </header>
  <p>原文链接：<a href="http://www.hackswjtu.com/Running-or-Safe/">www.hackswjtu.com</a></p>
<p>作者：冬瓜</p>
<hr />
<blockquote>
  <p>最近由于礼品机制，官方服务器人工查询可能较为严格。所以在实验的时候切勿使用个人账号进行脚本刷数据，以免造成被拉黑的情况。</p>
</blockquote>
<p>上个礼拜，我们的小组织 <a href="https://github.com/HackSwjtu">HackSwjtu</a> 破解了 <em>运动世界校园</em> 这款 app。与其说是破解 app，不如说是我们破解了它的网络接口。</p>
<p>以下是我们进行这个小项目的全部过程。</p>
<h2 id="section">意外截获请求负载信息</h2>
<p><em>运动世界校园</em> 拥有一套很有意思的跑步规则，在选择目标距离后，在地图上回“随机”给出多个待检测点，而在这些点中，你必须要经过几个，路线随意，这样才完成了跑步评测的第一步。而在跑步结束后，软件还会计算你的跑步平均速度，如果偏差太大（过快或过慢）也不会记录成为有效成绩。</p>
<p>好奇心驱使下，我们对其进行抓包，想看一看大致的实现过程。我们分别对<strong>设置目标距离</strong>、<strong>产生随机点</strong>和<strong>上传数据</strong>三个请求进行了抓包，其结果如下（测试环境 iOS 9.3）：</p>
<h3 id="section-1">设置目标点 及 产生随机点</h3>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">POST</span> <span class="ss">http</span><span class="p">:</span><span class="sr">//</span><span class="n">gxapp</span><span class="o">.</span><span class="n">iydsj</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">api</span><span class="o">/</span><span class="n">v2</span><span class="o">/</span><span class="n">campus</span><span class="o">/</span><span class="mi">901</span><span class="o">/</span><span class="n">get</span><span class="o">/</span><span class="mi">1</span><span class="o">/</span><span class="n">distance</span><span class="o">/</span><span class="mi">3</span> 
<span class="ss">Host</span><span class="p">:</span> <span class="n">gxapp</span><span class="o">.</span><span class="n">iydsj</span><span class="o">.</span><span class="n">com</span>
<span class="ss">uid</span><span class="p">:</span> <span class="mi">47881</span>
<span class="ss">Accept</span><span class="p">:</span> <span class="o">*/*</span>
<span class="ss">Authorization</span><span class="p">:</span> <span class="no">Basic</span> <span class="no">MTRwXBd3MjU1MzU6MTk5NzAyLjZXWGz</span><span class="o">=</span>
<span class="no">Proxy</span><span class="o">-</span><span class="ss">Connection</span><span class="p">:</span> <span class="n">keep</span><span class="o">-</span><span class="n">alive</span>
<span class="ss">osType</span><span class="p">:</span> <span class="mi">1</span>
<span class="ss">appVersion</span><span class="p">:</span> <span class="mi">1</span><span class="o">.</span><span class="mi">2</span><span class="o">.</span><span class="mi">0</span>
<span class="no">Accept</span><span class="o">-</span><span class="ss">Language</span><span class="p">:</span> <span class="n">zh</span><span class="o">-</span><span class="no">Hans</span><span class="o">-</span><span class="no">CN</span><span class="p">;</span><span class="n">q</span><span class="o">=</span><span class="mi">1</span>
<span class="no">Accept</span><span class="o">-</span><span class="ss">Encoding</span><span class="p">:</span> <span class="n">gzip</span><span class="p">,</span> <span class="n">deflate</span>
<span class="no">Content</span><span class="o">-</span><span class="ss">Type</span><span class="p">:</span> <span class="n">application</span><span class="o">/</span><span class="n">json</span>
<span class="ss">DeviceId</span><span class="p">:</span> <span class="no">FC139628</span><span class="o">-</span><span class="no">F5F6</span><span class="o">-</span><span class="mi">423</span><span class="n">A</span><span class="o">-</span><span class="no">ADBF</span><span class="o">-</span><span class="no">C8E310FCB713</span>
<span class="ss">CustomDeviceId</span><span class="p">:</span> <span class="no">FC139628</span><span class="o">-</span><span class="no">F5F6</span><span class="o">-</span><span class="mi">423</span><span class="n">A</span><span class="o">-</span><span class="no">ADBF</span><span class="o">-</span><span class="no">C8E310FCB713_iOS_sportsWorld_campus</span>
<span class="no">Content</span><span class="o">-</span><span class="ss">Length</span><span class="p">:</span> <span class="mi">45</span>
<span class="no">User</span><span class="o">-</span><span class="ss">Agent</span><span class="p">:</span> <span class="no">SWCampus</span><span class="o">/</span><span class="mi">1</span><span class="o">.</span><span class="mi">2</span><span class="o">.</span><span class="mi">0</span> <span class="p">(</span><span class="n">iPhone</span><span class="p">;</span> <span class="n">iOS</span> <span class="mi">9</span><span class="o">.</span><span class="mi">3</span><span class="o">.</span><span class="mi">4</span><span class="p">;</span> <span class="no">Scale</span><span class="o">/</span><span class="mi">3</span><span class="o">.</span><span class="mo">00</span><span class="p">)</span>
<span class="ss">Connection</span><span class="p">:</span> <span class="n">keep</span><span class="o">-</span><span class="n">alive</span>
<span class="ss">json</span><span class="p">:</span> <span class="p">{</span><span class="s2">&quot;longitude&quot;</span><span class="p">:</span><span class="mi">103</span><span class="o">.</span><span class="mi">991842</span><span class="p">,</span><span class="s2">&quot;latitude&quot;</span><span class="p">:</span><span class="mi">30</span><span class="o">.</span><span class="mi">766178</span><span class="p">}</span></code></pre></div>
<h3 id="section-2">数据上传</h3>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">POST</span> <span class="ss">http</span><span class="p">:</span><span class="sr">//</span><span class="n">gxapp</span><span class="o">.</span><span class="n">iydsj</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">api</span><span class="o">/</span><span class="n">v2</span><span class="o">/</span><span class="n">users</span><span class="o">/</span><span class="mi">47881</span><span class="o">/</span><span class="n">running_records</span><span class="o">/</span><span class="n">add</span> 
<span class="ss">Host</span><span class="p">:</span> <span class="n">gxapp</span><span class="o">.</span><span class="n">iydsj</span><span class="o">.</span><span class="n">com</span>
<span class="ss">uid</span><span class="p">:</span> <span class="mi">47881</span>
<span class="ss">Accept</span><span class="p">:</span> <span class="o">*/*</span>
<span class="ss">Authorization</span><span class="p">:</span> <span class="no">Basic</span> <span class="no">MTRwXBd3MjU1MzU6MTk5NzAyLjZXWGz</span><span class="o">=</span>
<span class="no">Proxy</span><span class="o">-</span><span class="ss">Connection</span><span class="p">:</span> <span class="n">keep</span><span class="o">-</span><span class="n">alive</span>
<span class="ss">osType</span><span class="p">:</span> <span class="mi">1</span>
<span class="ss">appVersion</span><span class="p">:</span> <span class="mi">1</span><span class="o">.</span><span class="mi">2</span><span class="o">.</span><span class="mi">0</span>
<span class="no">Accept</span><span class="o">-</span><span class="ss">Language</span><span class="p">:</span> <span class="n">zh</span><span class="o">-</span><span class="no">Hans</span><span class="o">-</span><span class="no">CN</span><span class="p">;</span><span class="n">q</span><span class="o">=</span><span class="mi">1</span>
<span class="no">Accept</span><span class="o">-</span><span class="ss">Encoding</span><span class="p">:</span> <span class="n">gzip</span><span class="p">,</span> <span class="n">deflate</span>
<span class="no">Content</span><span class="o">-</span><span class="ss">Type</span><span class="p">:</span> <span class="n">application</span><span class="o">/</span><span class="n">json</span>
<span class="ss">DeviceId</span><span class="p">:</span> <span class="no">FC139628</span><span class="o">-</span><span class="no">F5F6</span><span class="o">-</span><span class="mi">423</span><span class="n">A</span><span class="o">-</span><span class="no">ADBF</span><span class="o">-</span><span class="no">C8E310FCB713</span>
<span class="ss">CustomDeviceId</span><span class="p">:</span> <span class="no">FC139628</span><span class="o">-</span><span class="no">F5F6</span><span class="o">-</span><span class="mi">423</span><span class="n">A</span><span class="o">-</span><span class="no">ADBF</span><span class="o">-</span><span class="no">C8E310FCB713_iOS_sportsWorld_campus</span>
<span class="no">Content</span><span class="o">-</span><span class="ss">Length</span><span class="p">:</span> <span class="mi">89183</span>
<span class="no">User</span><span class="o">-</span><span class="ss">Agent</span><span class="p">:</span> <span class="no">SWCampus</span><span class="o">/</span><span class="mi">1</span><span class="o">.</span><span class="mi">2</span><span class="o">.</span><span class="mi">0</span> <span class="p">(</span><span class="n">iPhone</span><span class="p">;</span> <span class="n">iOS</span> <span class="mi">9</span><span class="o">.</span><span class="mi">3</span><span class="o">.</span><span class="mi">4</span><span class="p">;</span> <span class="no">Scale</span><span class="o">/</span><span class="mi">3</span><span class="o">.</span><span class="mo">00</span><span class="p">)</span>
<span class="ss">Connection</span><span class="p">:</span> <span class="n">keep</span><span class="o">-</span><span class="n">alive</span>
<span class="ss">json</span><span class="p">:</span> <span class="p">{</span><span class="s2">&quot;totalDis&quot;</span><span class="p">:</span><span class="mi">3</span><span class="o">.</span><span class="mi">24</span><span class="p">,</span><span class="s2">&quot;sportType&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span><span class="s2">&quot;speed&quot;</span><span class="p">:</span><span class="mi">12</span><span class="p">,</span><span class="s2">&quot;fivePointJson&quot;</span><span class="ss">:&quot;{&quot;</span><span class="n">useZip</span><span class="s2">&quot; : false, &quot;</span><span class="n">fivePointJson</span><span class="s2">&quot; : &quot;</span><span class="o">[</span><span class="p">{</span><span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span><span class="s2">&quot;isPass&quot;</span><span class="ss">:true</span><span class="p">,</span><span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.772452&quot;</span><span class="p">,</span><span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;103.988141&quot;</span><span class="p">,</span><span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;0&quot;</span><span class="p">},{</span><span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span><span class="s2">&quot;isPass&quot;</span><span class="ss">:true</span><span class="p">,</span><span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.769404&quot;</span><span class="p">,</span><span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;103.991393&quot;</span><span class="p">,</span><span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;0&quot;</span><span class="p">},{</span><span class="s2">&quot;flag&quot;</span><span class="p">:</span> <span class="o">.</span><span class="n">.</span><span class="o">.</span>
<span class="sr">//</span> <span class="err">数据量过大，部分显示</span></code></pre></div>
<p>我们发现一个严重的问题，在这两步关键的操作上，没有我们经常见到的 token 认证，只是在请求头的 <em>Authorization</em> 中增加了一个字段验证。而且从格式上来看，很容易就能猜到这是个 <em>Base64</em> 转码方式。我们使用 Base64 解码方式将其转回，发现了具有如下规则：</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">Basic</span> <span class="o">[</span><span class="n">username</span><span class="o">]</span><span class="p">:</span><span class="o">[</span><span class="n">passward</span><span class="o">]</span></code></pre></div>
<p>这是一个极不负责任的认证提交数据方式。试想，如果用户非正常方式进行提交数据，因为不经过分发 token 进行在线认证，<strong>很容易就能造出虚假数据出来</strong>。</p>
<p>是的，我们就是这么做的。</p>
<h2 id="section-3">进行跑步数据的处理及分析</h2>
<p>我们展示一个接近完整的跑步数据：</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="p">{</span>
	<span class="s2">&quot;totalDis&quot;</span><span class="p">:</span><span class="mi">3</span><span class="o">.</span><span class="mi">24</span><span class="p">,</span>
	<span class="s2">&quot;sportType&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
	<span class="s2">&quot;speed&quot;</span><span class="p">:</span><span class="mi">12</span><span class="p">,</span>
	<span class="s2">&quot;fivePointJson&quot;</span><span class="p">:</span>
		<span class="s2">&quot;{</span>
<span class="s2">			&quot;</span><span class="n">useZip</span><span class="s2">&quot; : false,  </span>
<span class="s2">			&quot;</span><span class="n">fivePointJson</span><span class="s2">&quot; : 				</span>
<span class="s2">            &quot;</span><span class="o">[</span><span class="p">{</span>
				<span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isPass&quot;</span><span class="ss">:true</span><span class="p">,</span>
				<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.772452&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;103.988141&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;0&quot;</span>
			<span class="p">},</span>
			<span class="p">{</span>
				<span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isPass&quot;</span><span class="ss">:true</span><span class="p">,</span>
				<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.769404&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;103.991393&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;0&quot;</span>
			<span class="p">},</span>
			<span class="p">{</span>
				<span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isPass&quot;</span><span class="ss">:true</span><span class="p">,</span>
				<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.768566&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;103.989982&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;0&quot;</span>
			<span class="p">},</span>	
			<span class="p">{</span>
				<span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isPass&quot;</span><span class="ss">:false</span><span class="p">,</span>
				<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.774981&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;104.000061&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;0&quot;</span>
			<span class="p">},</span>
			<span class="p">{</span>
				<span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isPass&quot;</span><span class="ss">:true</span><span class="p">,</span>
				<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.775152&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;103.990113&quot;</span><span class="p">,</span>
				<span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;1&quot;</span>
			<span class="p">}</span><span class="o">]</span><span class="s2">&quot;}&quot;</span><span class="p">,</span>
		<span class="s2">&quot;selDistance&quot;</span><span class="p">:</span><span class="mi">3</span><span class="p">,</span>
		<span class="s2">&quot;unCompleteReason&quot;</span><span class="p">:</span><span class="mi">4</span><span class="p">,</span>
		<span class="s2">&quot;allLocJson&quot;</span><span class="p">:</span>
		<span class="s2">&quot;{</span>
<span class="s2">			&quot;</span><span class="n">useZip</span><span class="s2">&quot; : false,  </span>
<span class="s2">			&quot;</span><span class="n">allLocJson</span><span class="s2">&quot; : 		</span>
<span class="s2">			&quot;</span><span class="o">[</span><span class="p">{</span>
				<span class="s2">&quot;speed&quot;</span><span class="ss">:&quot;0&quot;</span><span class="p">,</span>
				<span class="s2">&quot;id&quot;</span><span class="ss">:&quot;1&quot;</span><span class="p">,</span>
				<span class="s2">&quot;pointid&quot;</span><span class="ss">:&quot;1&quot;</span><span class="p">,</span>
				<span class="s2">&quot;radius&quot;</span><span class="ss">:&quot;65.000000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;gaintime&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;createtime&quot;</span><span class="ss">:&quot;&quot;</span><span class="p">,</span>
				<span class="s2">&quot;modifytime&quot;</span><span class="ss">:&quot;&quot;</span><span class="p">,</span>
				<span class="s2">&quot;type&quot;</span><span class="ss">:&quot;5&quot;</span><span class="p">,</span>
				<span class="s2">&quot;totaldis&quot;</span><span class="ss">:&quot;0&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.766170&quot;</span><span class="p">,</span>
				<span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;avgspeed&quot;</span><span class="ss">:&quot;0&quot;</span><span class="p">,</span>
				<span class="s2">&quot;totaltime&quot;</span><span class="ss">:&quot;2.000000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lng&quot;</span><span class="ss">:&quot;103.991934&quot;</span><span class="p">,</span>
				<span class="s2">&quot;locationtype&quot;</span><span class="ss">:&quot;0&quot;</span>
			<span class="p">},</span>
			<span class="o">.</span><span class="n">.</span><span class="o">.</span><span class="n">.</span><span class="p">,</span>
			<span class="p">{</span>
				<span class="s2">&quot;speed&quot;</span><span class="ss">:&quot;0&quot;</span><span class="p">,</span>
				<span class="s2">&quot;id&quot;</span><span class="ss">:&quot;294&quot;</span><span class="p">,</span>
				<span class="s2">&quot;pointid&quot;</span><span class="ss">:&quot;294&quot;</span><span class="p">,</span>
				<span class="s2">&quot;radius&quot;</span><span class="ss">:&quot;10.000000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;gaintime&quot;</span><span class="ss">:&quot;1476260686000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;createtime&quot;</span><span class="ss">:&quot;&quot;</span><span class="p">,</span>
				<span class="s2">&quot;modifytime&quot;</span><span class="ss">:&quot;&quot;</span><span class="p">,</span>
				<span class="s2">&quot;type&quot;</span><span class="ss">:&quot;6&quot;</span><span class="p">,</span>
				<span class="s2">&quot;totaldis&quot;</span><span class="ss">:&quot;3241&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.766135&quot;</span><span class="p">,</span>
				<span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;avgspeed&quot;</span><span class="ss">:&quot;0&quot;</span><span class="p">,</span>
				<span class="s2">&quot;totaltime&quot;</span><span class="ss">:&quot;2159.000000&quot;</span><span class="p">,</span>
				<span class="s2">&quot;lng&quot;</span><span class="ss">:&quot;103.992010&quot;</span><span class="p">,</span>
				<span class="s2">&quot;locationtype&quot;</span><span class="ss">:&quot;0&quot;</span>
			<span class="p">}</span><span class="o">]</span>
		<span class="s2">&quot;}&quot;</span><span class="p">,</span>
	<span class="s2">&quot;complete&quot;</span><span class="ss">:true</span><span class="p">,</span>
	<span class="s2">&quot;startTime&quot;</span><span class="p">:</span><span class="mi">1476258220000</span><span class="p">,</span>
	<span class="s2">&quot;stopTime&quot;</span><span class="p">:</span><span class="mi">1476260686000</span><span class="p">,</span>
	<span class="s2">&quot;totalTime&quot;</span><span class="p">:</span><span class="mi">2466</span>
<span class="p">}</span></code></pre></div>
<p>其中我们仍然省略了大量的跑步打点数据，因为实在是太多。根据 json 数据每个属性的名字，我们能猜出个大概。而且在最外层数据中，我们发现 ：<code>totalDis</code>、<code>speed</code> 、 <code>fivePointJson</code> 、 <code>complete</code> 、 <code>startTime</code> 、 <code>stopTime</code> 、 <code>totalTime</code> 这几个属性，这是一件很可笑的事情。<strong>对于所有的数据处理，都是在 client 端进行的，而后台的服务器仅仅提供了数据库的记录作用</strong>。</p>
<p>经过几组数据的测试，我们发现在 server 端，仅仅对当次提交的 <code>speed</code> 数据进行判断，而 <code>speed</code> 数据居然没有经过 <code>totalTime</code> 和 <code>totalDis</code> 的验证。<strong>而后两者仅仅是用来在 client 端起显示作用（奇葩的逻辑）</strong>。</p>
<p>而对于 <code>startTime</code> 和 <code>stopTime</code> 两个属性，自然就能猜测到这是系统默认生成的当前时间的时间戳，从末尾的三个0就可以暴露出它设置成为毫秒级别。</p>
<p>我们再来看 <code>fivePointJson</code> 这个属性的结构：</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="s2">&quot;flag&quot;</span><span class="ss">:&quot;1476258220000&quot;</span><span class="p">,</span>
<span class="s2">&quot;isPass&quot;</span><span class="ss">:true</span><span class="p">,</span>
<span class="s2">&quot;lat&quot;</span><span class="ss">:&quot;30.775152&quot;</span><span class="p">,</span>
<span class="s2">&quot;lon&quot;</span><span class="ss">:&quot;103.990113&quot;</span><span class="p">,</span>
<span class="s2">&quot;isFixed&quot;</span><span class="ss">:&quot;1&quot;</span></code></pre></div>
<p><code>flag</code> 自然也是时间戳，并且可以惊讶的发现他与 <code>startTime</code> 相同。而是否通过，仅仅使用了 <code>isPass</code> 这个布尔值来记录。实在是令人无语。</p>
<p>我们将数据保存下来，进行一次虚假提交，不出意外增加了一次新的记录。</p>
<p><img src="http://7xwh85.com1.z0.glb.clouddn.com/ss.jpg" width="300px" /></p>
<p>但是知道了这些，我们还是无法解决一个重要的问题，即跑步路径坐标。并且在我们的提交尝试中，如果跑步路径的 json 格式提交错误，就会造成在 client 端无法显示 Running Route 的问题。由于这个 app 使用了百度地图第三方sdk，所以我们的第一想法是通过百度地图路径规划功能，从一条路径中取点进行构造 route。可是在构造的时候会遇到很多问题，比如取点的距离与跑步速度不统一等等，其问题可以参见我们的 <em><a href="https://github.com/HackSwjtu/HackRunningGo-iOS">HaRunGo iOS repo</a></em> 。</p>
<p>而在 app 中会有一个 <em>约跑功能</em> ，我们可以看见他人的跑步路线。因此我们打算采取偷梁换柱的方式，将他人跑步数据进行抓取，进而修改成自己此时的信息及时间戳即可。</p>
<h3 id="section-4">约跑请求</h3>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="p">{</span>
	<span class="s2">&quot;error&quot;</span><span class="p">:</span><span class="mi">10000</span><span class="p">,</span>
	<span class="s2">&quot;message&quot;</span><span class="ss">:&quot;成功&quot;</span><span class="p">,</span>
	<span class="s2">&quot;data&quot;</span><span class="p">:</span>
	<span class="p">{</span>
		<span class="s2">&quot;roomInfoModel&quot;</span><span class="p">:</span>
		<span class="p">{</span>
			<span class="s2">&quot;beginTime&quot;</span><span class="ss">:&quot;2016-10-21 20:17:13&quot;</span><span class="p">,</span>
			<span class="s2">&quot;endTime&quot;</span><span class="ss">:&quot;2016-10-21 20:44:42&quot;</span><span class="p">,</span>
			<span class="s2">&quot;distance&quot;</span><span class="p">:</span><span class="mi">3</span><span class="o">.</span><span class="mi">0</span><span class="p">,</span>
			<span class="s2">&quot;locDesc&quot;</span><span class="ss">:&quot;人体机能实验室&quot;</span><span class="p">,</span>
			<span class="s2">&quot;finishNum&quot;</span><span class="p">:</span><span class="mi">2</span>
		<span class="p">},</span>
		<span class="s2">&quot;roomersModelList&quot;</span><span class="p">:</span>
		<span class="o">[</span><span class="p">{</span>
			<span class="s2">&quot;finished&quot;</span><span class="ss">:true</span><span class="p">,</span>
			<span class="s2">&quot;uid&quot;</span><span class="p">:</span><span class="mi">57446</span><span class="p">,</span>
			<span class="s2">&quot;unid&quot;</span><span class="p">:</span><span class="mi">901</span><span class="p">,</span>
			<span class="s2">&quot;icon&quot;</span><span class="p">:</span>
			<span class="s2">&quot;http://imgs.gxapp.iydsj.com/imgs/d30a0bff-1b20-4504-91b9-49ae65ada0a6.jpeg&quot;</span><span class="p">,</span>
			<span class="s2">&quot;sex&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
			<span class="s2">&quot;name&quot;</span><span class="ss">:&quot;杨xx&quot;</span><span class="p">,</span>
			<span class="s2">&quot;endTime&quot;</span><span class="ss">:&quot;2016-10-21 20:44:42&quot;</span><span class="p">,</span>
			<span class="s2">&quot;points&quot;</span><span class="ss">:&quot;{...}&quot;</span>
		<span class="p">},</span>
		<span class="p">{</span>
			<span class="s2">&quot;finished&quot;</span><span class="ss">:true</span><span class="p">,</span>
			<span class="s2">&quot;uid&quot;</span><span class="p">:</span><span class="mi">57276</span><span class="p">,</span>
			<span class="s2">&quot;unid&quot;</span><span class="p">:</span><span class="mi">901</span><span class="p">,</span>
			<span class="s2">&quot;icon&quot;</span><span class="ss">:&quot;http://imgs.gxapp.iydsj.com/imgs/null&quot;</span><span class="p">,</span>
			<span class="s2">&quot;sex&quot;</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span>
			<span class="s2">&quot;name&quot;</span><span class="ss">:&quot;李x&quot;</span><span class="p">,</span>
			<span class="s2">&quot;endTime&quot;</span><span class="ss">:&quot;2016-10-21 20:44:42&quot;</span><span class="p">,</span>
			<span class="s2">&quot;points&quot;</span><span class="ss">:&quot;{...}&quot;</span>
		<span class="p">},</span><span class="o">.</span><span class="n">.</span><span class="o">.</span>
		<span class="o">]</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></div>
<p>为了保护大家的隐私，我没有展示完整姓名。从获取到的数据中，我们发现 <code>points</code> 的格式与我们想要的跑步路线是完全一致的。因此我们对其进行数据解析，并处理时间戳生成我们所需要的数据。进而再将处理过后的数据进行整合，通过上传数据接口对个人用户进行认证，制造一条近乎完美的跑步数据出来。</p>
<blockquote>
  <p>其上传数据及处理数据可以阅读我们的上传数据脚本 <a href="https://github.com/HackSwjtu/HackRunningGo-SC/blob/master/HaRunGo.py">HaRunGo</a>，而对于网络约跑的采点流程可以详见更新静态跑步路线脚本 <a href="https://github.com/HackSwjtu/HackRunningGo-SC/blob/master/updateRoutes.py">updateRoutes.py</a></p>
</blockquote>
<h2 id="hackrunninggo-sc-work-flow">HackRunningGo-SC Work Flow</h2>
<p>我们对于以上的分析及实验进行整合，将所有的工作流程完整的写在了两个 Python 脚本中，并且开源以便大家学习、以便学校修正 bug 使用。可以详见我们的 <a href="https://github.com/HackSwjtu/HackRunningGo-SC">GitHub repo</a></p>
<p>如果想尝试使用，请先确保你具有 <code>Python 2.7</code> 的系统环境，然后依次按照以下流程：</p>
<h3 id="clone--hackrunninggo-sc-repo">1.clone 我们的 HackRunningGo-SC repo</h3>
<p>从 GitHub 上将我们的 repo clone 到本地，并访问 <em>HackRunningGo-SC</em> 目录：</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">git</span> <span class="nb">clone</span> <span class="ss">https</span><span class="p">:</span><span class="sr">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="no">HackSwjtu</span><span class="o">/</span><span class="no">HackRunningGo</span><span class="o">-</span><span class="no">SC</span><span class="o">.</span><span class="n">git</span> 
<span class="n">cd</span> <span class="no">HackRunningGo</span><span class="o">-</span><span class="no">SC</span></code></pre></div>
<p><img src="http://7xwh85.com1.z0.glb.clouddn.com/A96C4679-72D9-4F60-A50C-E51CD40657ED.png" alt="A96C4679-72D9-4F60-A50C-E51CD40657ED" /></p>
<h3 id="section-5">2.更新本地跑步路线静态数据（可选择）</h3>
<p>从约跑记录中将数据取出，并将所需数据收集至 <code>route.data</code> 文件中。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">python</span> <span class="n">updateRoutes</span><span class="o">.</span><span class="n">py</span></code></pre></div>
<h3 id="userdata-">3.在 <code>user.data</code> 中添加用户信息</h3>
<p>在 <code>user.data</code> 文件中添加登录所需的用户名和密码，<strong>一行一条，以空格分割</strong>。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">bash</span> <span class="p">\</span><span class="o">[</span><span class="nb">id</span><span class="o">]</span> <span class="o">[</span><span class="n">password</span><span class="o">]</span> <span class="o">&gt;&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">data</span>
<span class="n">cat</span> <span class="n">user</span><span class="o">.</span><span class="n">data</span></code></pre></div>
<p><img src="http://7xwh85.com1.z0.glb.clouddn.com/ss2.jpg" alt="ss2" /></p>
<h3 id="section-6">4.运行主脚本将路线录入</h3>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">python</span> <span class="no">HaRunGo</span><span class="o">.</span><span class="n">py</span></code></pre></div>
<p>整个使用流程是十分简单的，但是这个脚本希望大家能作为学习参考，更希望官方能对 body 中的数据进行更加严格的加密，对登录状况采取更加科学的 token 认证方式。</p>
<h2 id="section-7">再谈信息泄露问题</h2>
<p>在约跑记录网络接口中，我们能够获取到每个用户的真实姓名、性别、头像，<strong>这是极其严重的个人信息泄露</strong>！</p>
<p>从今年 5 月份阿里安全部门的大牛 @蒸米spark 在微博上爆料搜狗和百度输入在采集个人聊天习惯的同时，上传数据居然使用明文进行数据提交。在整个流程中使用 http 协议，丝毫没有考虑数据加密的问题。</p>
<p>而在跑步记录的上传中，毫无例外也采用了明文的方式。更加让人气愤的是，在约跑功能中，很轻易的就能拿到他人姓名和性别信息。这些泄露方式很有可能为诈骗者提供更快捷的信息渠道，而大学生也是初入社会的学生团体，社会阅历及信息保护的意识经验远远不足，更应该是各大互联网公司着重保护的对象集体。</p>
<p>一旦一块移动客户端 app 与个人的身体信息、聊天信息、财政信息相关联时，就要时刻主要到对于用户信息的保护。从之前的 163 邮箱事件、icloud 相册泄露事件再到最近沸沸扬扬的<a href="http://usa.people.com.cn/n1/2016/0923/c241376-28735538.html">雅虎邮寄信息泄露事件</a>，网民用户的安全问题日益严峻。而如今的校园跑步软件，没有实名制认证机制可以随意注册，真的太过于裸露。</p>
<p>在斥责 app 制作公司的同时，也提醒广大用户多加注意个人隐私的保护，提高个人信息的安全意识，在有法却无严厉监管的环境下我们只有自我提高。（这实属无奈之举）</p>
<h2 id="section-8">写在最后</h2>
<p>这篇文章是我们 <a href="https://github.com/HackSwjtu">HackSwjtu</a> 的第一篇公示技术博文，以此希望 <em>运动世界校园</em> 的供应商 <strong>杭州万航信息科技有限公司</strong> 早日对数据问题进行修复更新，也希望我交大的信息学院在关注学科排名的同时，提升学院技术。</p>
<p>当然，如果你是 SWJTU 的一名 Hack，或是一名 Geek，并且有志于加入我们的 GitHub 组织，你可以通过<a href="http://www.hackswjtu.com/I-want-you/">这个链接</a>，并且按照其中的联系方式联系我。我会及时反馈，并安排线上面试。</p>
<p><img src="http://ofmxkmiv3.bkt.clouddn.com/banner.png" alt="" /></p>
  <footer class="post-footer">
    <section class="author">
      <h4>Desgard_Duan</h4>
      <p>I write many code to write less code.💻</p>
    </section>
<aside class="share">
  <h4>Share this.</h4>
  <a href="http://twitter.com/share?text=《玩转运动世界校园》 -- Guardia · 瓜地&amp;url=https://www.desgard.com/Running-Or-Safe/"
  onclick="window.open(this.href, 'twitter-share', 'width=550,height=235');return false;">
    <i class="fa fa-twitter-square"></i>
  </a>
  <a href="http://v.t.sina.com.cn/share/share.php?url=https://www.desgard.com/Running-Or-Safe/&amp;title=《玩转运动世界校园》 —— Guardia · 瓜地" onclick="window.open(this.href, 'twitter-share', 'width=550,height=235');return false;">
    <i class="fa fa-weibo"></i>
  </a>
</aside>
      <hr>
<aside id="comments" class="disqus">
  <div id="container"></div>
  <!-- <link rel="stylesheet" href="/assets/css/gitment.css">
  <script src="https://imsun.github.io/gitment/dist/gitment.browser.js"></script>
  <script>
  var gitment = new Gitment({
    id: "https://www.desgard.com/Running-Or-Safe/", 
    owner: 'Desgard',
    repo: 'desgard.github.com',
    oauth: {
      client_id: 'e2612df42f3f2a83e71c',
      client_secret: 'b53e85b314bb24a6d06773e48bbb62a4de3b8b3a',
    },
  })
  gitment.render('container')
  </script> -->
<link rel="stylesheet" href="/assets/css/gitalk.css">
<script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>
<div id='gitalk-container'></div>
<script>
    const gitalk = new Gitalk({
        id: "https://www.desgard.com/Running-Or-Safe/", 
        clientID: 'e2612df42f3f2a83e71c',
        clientSecret: 'b53e85b314bb24a6d06773e48bbb62a4de3b8b3a',
        repo: 'desgard.github.com',
        owner: 'Desgard',
        admin: ['Desgard'],
        // facebook-like distraction free mode
        distractionFreeMode: false
    })
    gitalk.render('gitalk-container')
</script>
</aside>
  </footer>
</article>
    </main>
<footer class="footer">
  <div class="container">
    <ul class="icons">
      <li>
        <a href="https://github.com/desgard" class="icon-github" target="_blank">
          <i class="fa fa-github"></i>
        </a>
      </li>
      <li>
        <a href="https://www.facebook.com/desgard.duan" class="icon-facebook" target="_blank">
          <i class="fa fa-facebook"></i>
        </a>
      </li>
      <li>
        <a href="https://twitter.com/Desgard_Duan" class="icon-twitter" target="_blank">
          <i class="fa fa-twitter"></i>
        </a>
      </li>
      <li>
        <a href="https://stackoverflow.com/users/6119149/desgard-duan" class="icon-github" target="_blank">
          <i class="fa fa-stack-overflow"></i>
        </a>
      </li>
      <li>
        <a href="https://weibo.com/desgard" class="icon-instagram" target="_blank">
          <i class="fa fa-weibo"></i>
        </a>
      </li>
    </ul>
    <p>
      <q>I write many code to write less code.💻</q>
      <small>– Gua</small>
    </p>
    <small class="clearfix">
      Powered by <a href="http://jekyllrb.com" target="_blank">Jekyll</a> • <a href="https://github.com/desgard" target="_blank">Open source <i class="fa fa-heart"></i></a>
    </small>
  </div>
</footer>
<a class="scroll-up fa fa-chevron-up bounce" href="#" data-position="0"></a>
<div id="modalSearch" class="modal">
  <div class="modal__overlay"></div>
  <div class="modal__content">
    <a href="#!" class="modal-close" data-modal-close>&times;</a>
    <div class="search-container">
      <input type="text" id="search-input" placeholder="Search articles">
      <ul id="results-container"></ul>
    </div>
  </div>
</div>
    <script src="/assets/main-52d417e8a6ff9f5b168386d37c96338a.js"></script>
  </body>
  <script>
    var link = "" ;
    var os = function() {  
      var ua = navigator.userAgent,  
      isWindowsPhone = /(?:Windows Phone)/.test(ua),  
      isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone,   
      isAndroid = /(?:Android)/.test(ua),   
      isFireFox = /(?:Firefox)/.test(ua),   
      isChrome = /(?:Chrome|CriOS)/.test(ua),  
      isTablet = /(?:iPad|PlayBook)/.test(ua) || (isAndroid && !/(?:Mobile)/.test(ua)) || (isFireFox && /(?:Tablet)/.test(ua)),  
      isPhone = /(?:iPhone)/.test(ua) && !isTablet,  
      isPc = !isPhone && !isAndroid && !isSymbian;  
      return {  
        isTablet: isTablet,  
        isPhone: isPhone,  
        isAndroid : isAndroid,  
        isPc : isPc  
      };  
    }();  
    if (link.length > 0) {
      if (os.isAndroid || os.isPhone) {
        location.replace(link);
      }
    }
  </script>
</html>